package command

import (
	"fmt"
	"image"
	"image/draw"
	"image/jpeg"
	"imgtools/lib/file"
	"imgtools/lib/log"
	"os"
	"path"
	"strings"

	"github.com/urfave/cli/v2"
)

type cutOption struct {
	input   string
	outdir  string
	quality int
}

var Cut = &cli.Command{
	Name:        "cut",
	Usage:       "cut [options] [input]",
	Description: "把长图片切割成小图",
	Flags: []cli.Flag{
		&cli.StringFlag{
			Name:    "outdir",
			Aliases: []string{"o"},
			Usage:   "结果图片保存目录",
		},
		&cli.IntFlag{
			Name:    "quality",
			Value:   80,
			Aliases: []string{"q"},
			Usage:   "图片的质量",
		},
	},
	Action: func(ctx *cli.Context) error {
		outdir := ctx.String("outdir")
		fmt.Println(outdir)
		list := ctx.Args().Slice()
		if len(list) == 0 {
			log.Println("请输入要处理的图片")
		}
		for _, input := range list {
			if !file.IsFileExists(input) {
				log.Printfln("[%s]不存在", input)
				continue
			}
			dealCut(cutOption{
				input:   input,
				outdir:  outdir,
				quality: ctx.Int("quality"),
			})
		}
		return nil
	},
}

func dealCut(opt cutOption) error {
	fi, e := os.Open(opt.input)
	if e != nil {
		return e
	}
	defer fi.Close()

	img, _, err := image.Decode(fi)
	if err != nil {
		return err
	}
	bounds := img.Bounds()
	width := bounds.Max.X
	height := bounds.Max.Y

	filename := path.Base(opt.input)
	ext := path.Ext(filename)
	filename = strings.ReplaceAll(filename, ext, "")

	outdir := opt.outdir
	if outdir == "" {
		outdir = path.Join(path.Dir(opt.input), fmt.Sprintf("result-%d", opt.quality))
	}
	file.Mkdirp(outdir)
	if height > width {
		num := height/width + 1
		for i := 0; i < num; i++ {
			startY := width * i
			endY := startY + width
			if endY > height {
				endY = height
			}

			imgSub := image.NewRGBA(image.Rect(0, 0, width, endY-startY))
			draw.Draw(imgSub, image.Rectangle{
				Min: image.Point{
					X: 0,
					Y: 0,
				},
				Max: image.Point{
					X: width,
					Y: endY - startY,
				},
			}, img, image.Point{0, startY}, draw.Over)

			saveFile := path.Join(outdir, fmt.Sprintf("%s-%d%s", filename, i, ext))
			fo, eFo := os.OpenFile(saveFile, os.O_CREATE|os.O_WRONLY, os.ModePerm)
			if eFo != nil {
				log.Printfln("[%s]保存失败: %v", saveFile, eFo)
				continue
			}
			defer fo.Close()
			if e := jpeg.Encode(fo, imgSub, &jpeg.Options{
				Quality: opt.quality,
			}); e == nil {
				log.Printfln("[%s] %d 保存成功", saveFile, opt.quality)
			} else {
				log.Printfln("[%s]保存失败: %v", saveFile, e)
			}
		}
	}
	return nil
}
